package cn.stylefeng.guns.modular.gridsystem.netty.tcp;

import cn.stylefeng.guns.modular.gridsystem.config.TcpServerConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;

import java.nio.ByteOrder;

/**
 * @author ssy
 * @date 2022/4/12 9:20
 */
@Slf4j
public class TcpServer {

    @Autowired
    private TcpServerHandler serverHandler;

    @Autowired
    private TcpServerConfig serverConfig;

    @Async
    public void run() throws Exception {
        log.info("tcp server 启动中。。。");

        //初始化线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();// 用来接收进来的连接
        EventLoopGroup workerGroup = new NioEventLoopGroup();//用来处理已经被接收的连接

        try {
            //初始化服务端配置
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //绑定线程组
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)//使用NioServerSocketChannel作为服务器的通道实现
                    .option(ChannelOption.SO_BACKLOG, 128)//设置线程队列等待连接个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true)//保持长连接
                    .childOption(ChannelOption.SO_REUSEADDR, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) {//childHandler对应workerGroup  handler对应bossGroup
                    //绑定客户端连接时候触发操作
                    ChannelPipeline pipeline = ch.pipeline();
                    //添加解码器，将数据从byte解析为对象
                    pipeline.addLast(new LengthFieldBasedFrameDecoder(
                            ByteOrder.BIG_ENDIAN,
                            Integer.MAX_VALUE,5,4,0,9,true));
                    pipeline.addLast(new MessageDecoder());
                    //业务处理
                    pipeline.addLast(serverHandler);
                    //心跳检测长时间没有写入或者可读取数据的连接会被移除
                    pipeline.addLast(new IdleStateHandler(5,5,0));

                }
            });
            //启动服务器绑定一个端口并且同步
            ChannelFuture sync = serverBootstrap.bind(serverConfig.getPort()).sync();// 绑定端口，开始接收进来的连接
            log.info("tcp server启动成功");
            // 对关闭通道进行监听
            sync.channel().closeFuture().await();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

}
